home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 3 / Gold Medal Software - Volume 3 (Gold Medal) (1994).iso / graphics / 3dvect30.arj / PMODE.ASM < prev    next >
Assembly Source File  |  1993-11-18  |  70KB  |  2,036 lines

  1. ; PMODE v2.1232 raw, DPMI, VCPI, & XMS compliant protected mode header.
  2. ; By Tran (a.k.a. Thomas Pytel) of Renaissance.
  3.  
  4.         .386p
  5.         jumps
  6.  
  7. LOWMIN          = 0             ; minimum free low memory (in K)
  8. EXTMIN          = 0             ; minimum free extended memory (in K)
  9. STAKLEN         = 500h          ; stack size in para (keep below or = 1000h)
  10. STAKSAFE        = 20h           ; safe stack space in para
  11.  
  12. code16  segment para public use16
  13. code16  ends
  14. code32  segment para public use32
  15. code32  ends
  16. codeend segment para stack use32 'stack'
  17. codeend ends
  18.  
  19. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  20. ; Real mode and 16bit code
  21. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  22. code16  segment para public use16
  23.         assume cs:code16, ds:code16
  24.         org 0
  25.  
  26. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  27. ; 16 bit common system data
  28. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  29. errmsg0         db      '386 or better not detected!!!',7,'$'
  30. errmsg1         db      'Not enough low memory!!!',7,'$'
  31. errmsg2         db      'This system is already in V86 mode!!!',7,'$'
  32. errmsg3         db      'Not enough extended memory!!!',7,'$'
  33. errmsg4         db      'Couldn''t enable A20 gate!!!',7,'$'
  34. errmsg5         db      'Extended memory allocation failure. (weird eh???)',7,'$'
  35.  
  36. nullint         db      0cfh            ; IRET instruction
  37. exitrout        dw      exit            ; exit routine, modified if XMS, VCPI
  38.  
  39. savedstakoff    dw      ?               ; current saved stack offset
  40. savedstakseg    dw      ?               ; current saved stack segment
  41.  
  42. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  43. ; 16 bit common system code
  44. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  45. ;═════════════════════════════════════════════════════════════════════════════
  46. intreal:                                ; real mode int, load FS and GS here
  47.         pushf
  48. ;-----------------------------------------------------------------------------
  49. callreal:                               ; real mode call, load FS and GS here
  50.         push cs
  51.         push offset icreald
  52.         mov fs,cs:v86r_fs
  53.         mov gs,cs:v86r_gs
  54.         mov eax,cs:v86r_eax
  55.         mov ecx,cs:v86r_ecx
  56.         mov edx,cs:v86r_edx
  57.         mov ebx,cs:v86r_ebx
  58.         mov esi,cs:v86r_esi
  59.         mov edi,cs:v86r_edi
  60.         mov ebp,cs:v86r_ebp
  61. ;-----------------------------------------------------------------------------
  62. icreal:                                 ; real mode int, call, or IRQ
  63.         db 66h,68h              ; PUSH destination addx
  64. icrealm1        dd      ?       ;
  65. icrealm0        db      ?       ; CLI or STI
  66.         retf
  67. ;-----------------------------------------------------------------------------
  68. icreald:                                ; done with real int or call
  69.         cli
  70.         pushf
  71.         pop cs:v86r_flags
  72.         mov cs:v86r_eax,eax
  73.         mov cs:v86r_ecx,ecx
  74.         mov cs:v86r_edx,edx
  75.         mov cs:v86r_ebx,ebx
  76.         mov cs:v86r_esi,esi
  77.         mov cs:v86r_edi,edi
  78.         mov cs:v86r_ebp,ebp
  79.         mov cs:v86r_ds,ds
  80.         mov cs:v86r_es,es
  81.         mov cs:v86r_fs,fs
  82.         mov cs:v86r_gs,gs
  83. icreald2:
  84.         mov ax,cs
  85.         mov ds,ax
  86. icrealm2        label word              ; return to pmode modifiable to JMP
  87. ;-----------------------------------------------------------------------------
  88.         mov ebx,ds:cp_savedstakoff      ; DPMI return to pmode
  89.         mov dx,ds:dp_savedstaksel
  90.         mov edi,offset dp_int3_d
  91.         mov si,ds:_selcode
  92.         mov cx,dx
  93.         mov ax,ds:_seldata
  94.         jmp ds:d_switchaddx
  95. ;-----------------------------------------------------------------------------
  96. VICREAL1D=(($-(icrealm2+2))shl 8)+0ebh
  97. v_icreal1d:                             ; VCPI return to pmode from safe
  98.         mov edi,offset cp_int3_d
  99. ;-----------------------------------------------------------------------------
  100. ; EDI=offset to jump to in code32
  101. v_switchtopmode:                        ; VCPI switch to pmode
  102.         mov ds:v_ss_dest,edi
  103.         mov esi,offset v_ss_cr3
  104.         add esi,ds:_code16a
  105.         mov ax,0de0ch
  106.         int 67h
  107. ;-----------------------------------------------------------------------------
  108. CICREAL1D=(($-(icrealm2+2))shl 8)+0ebh
  109. c_icreal1d:                             ; custom return to pmode from safe
  110.         mov edi,offset cp_int3_d
  111. ;-----------------------------------------------------------------------------
  112. ; EDI=offset in pmode to jump to
  113. c_retpmode:                             ; reenter 32bit pmode
  114.         lgdt fword ptr c_gdt32addx      ; set up pmode GDT and IDT
  115.         lidt fword ptr c_idt32addx
  116.         mov ds:gdt32task[5],89h         ; set task as not busy
  117.         mov eax,cr0                     ; switch to pmode
  118.         or al,1
  119.         mov cr0,eax
  120.         db 0eah
  121.         dw $+4,20h
  122.         mov ax,30h                      ; load task register
  123.         ltr ax
  124.         jmp c_gotopmode
  125. ;-----------------------------------------------------------------------------
  126. if ($-(icrealm2+2)) gt 127
  127.   err
  128. endif
  129. CICREAL0D=(($-(icrealm2+2))shl 8)+0ebh
  130. c_icreal0d:                             ; return to pmode from normal
  131.         int 0ffh
  132. ;═════════════════════════════════════════════════════════════════════════════
  133. int32:                                  ; real mode INT32: EDX=off
  134.         pushad
  135.         push ds es fs gs
  136.         cli
  137.         mov ax,cs
  138.         mov ds,ax
  139.         mov ds:p_cpmodem0,edx
  140.         mov al,[esp+45]
  141.         shr al,1
  142.         and al,1
  143.         add al,0fah
  144.         mov ds:p_cpmodem1,al
  145.         push savedstakoff
  146.         push savedstakseg
  147.         movzx ebx,ds:nextmodestack
  148.         lea eax,[ebx-STAKSAFE*16]
  149.         mov ds:nextmodestack,ax
  150.         add ebx,ds:realstackbase
  151.         mov savedstakseg,ss
  152. int32m0         label   word            ; jump to pmode, modifiable
  153. ;-----------------------------------------------------------------------------
  154.         sub sp,ds:dp_savelen
  155.         mov savedstakoff,sp
  156.         mov ax,ss                       ; DPMI jump to pmode
  157.         mov es,ax
  158.         mov di,sp
  159.         xor al,al
  160.         call d_saveaddx
  161.         mov ax,ds:_seldata
  162.         mov cx,ax
  163.         mov dx,ax
  164.         mov edi,offset p_cpmode
  165.         mov si,ds:_selcode
  166.         jmp ds:d_switchaddx
  167. ;-----------------------------------------------------------------------------
  168. VINT32=(($-(int32m0+2))shl 8)+0ebh
  169. v_int32:                                ; VCPI call pmode
  170.         push ds:p_cpmodem2
  171.         mov ds:p_cpmodem2,VCPMODED
  172.         mov savedstakoff,sp
  173.         mov edi,offset p_cpmode1
  174.         jmp v_switchtopmode
  175. ;-----------------------------------------------------------------------------
  176. if ($-(int32m0+2)) gt 127
  177.   err
  178. endif
  179. CINT32=(($-(int32m0+2))shl 8)+0ebh
  180. c_int32:                                ; raw/XMS call pmode
  181.         push ds:p_cpmodem2
  182.         mov ds:p_cpmodem2,CCPMODED
  183.         mov savedstakoff,sp
  184.         mov edi,offset p_cpmode1
  185.         jmp c_retpmode
  186. ;═════════════════════════════════════════════════════════════════════════════
  187. int32d0:                                ; DPMI done with pmode call
  188.         mov di,sp
  189.         mov al,1
  190.         call d_saveaddx
  191.         add sp,ds:dp_savelen
  192. ;-----------------------------------------------------------------------------
  193. int32d2:                                ; done from all
  194.         pop savedstakseg
  195.         pop savedstakoff
  196.         add ds:nextmodestack,STAKSAFE*16
  197.         mov bx,ds:v86r_flags
  198.         mov ax,[esp+44]
  199.         and ax,not 8d5h
  200.         and bx,8d5h
  201.         or ax,bx
  202.         mov [esp+44],ax
  203.         pop gs fs es ds
  204.         popad
  205.         iret
  206. ;═════════════════════════════════════════════════════════════════════════════
  207. int32d1:                                ; VCPI done with pmode call
  208.         mov ss,savedstakseg
  209.         pop ds:p_cpmodem2
  210.         jmp int32d2
  211. ;═════════════════════════════════════════════════════════════════════════════
  212. int32d3:                                ; raw/XMS done with pmode call
  213.         mov c_retreal0m0,offset c_sicreal
  214.         mov ax,cs
  215.         mov ds,ax
  216.         movzx esp,savedstakoff
  217.         mov ss,savedstakseg
  218.         pop ds:p_cpmodem2
  219.         jmp int32d2
  220. ;─────────────────────────────────────────────────────────────────────────────
  221. chek_VCPI:                              ; Chek for VCPI
  222.         mov dx,offset v_emmname
  223.         mov ax,3d00h
  224.         int 21h
  225.         jc short chekVCPIa
  226.         mov bx,ax
  227.         mov ax,4400h
  228.         int 21h
  229.         jc short chekVCPIa
  230.         test dh,80h
  231.         jz short chekVCPIa
  232.         mov ax,4407h
  233.         int 21h
  234.         mov dl,al
  235.         mov ah,3Eh
  236.         int 21h
  237.         cmp dl,0FFh
  238.         jne short chekVCPIa
  239.         mov bx,1
  240.         mov ah,43h
  241.         int 67h
  242. ;       or ah,ah
  243. ;       jnz short chekVCPIa
  244.         mov v_emshandle,dx
  245.         mov ax,0de00h
  246.         int 67h
  247.         or ah,ah
  248.         clc
  249.         jz short chekVCPId
  250.         mov ah,45h
  251.         int 67h
  252. chekVCPIa:
  253.         stc
  254. chekVCPId:
  255.         ret
  256. ;─────────────────────────────────────────────────────────────────────────────
  257. chek_processor:                         ; Detect if current processor 386
  258.         pushf
  259.         xor ah,ah
  260.         push ax
  261.         popf
  262.         pushf
  263.         pop ax
  264.         and ah,0f0h
  265.         cmp ah,0f0h
  266.         je short detectno386
  267.         mov ah,0f0h
  268.         push ax
  269.         popf
  270.         pushf
  271.         pop ax
  272.         and ah,0f0h
  273.         jz short detectno386
  274.         popf
  275.         ret
  276. detectno386:
  277.         mov dx,offset errmsg0
  278.         jmp short exit16err
  279. ;─────────────────────────────────────────────────────────────────────────────
  280. chek_V86:                               ; Chek if already in V86 mode
  281.         smsw ax
  282.         test al,1
  283.         mov dx,offset errmsg2
  284.         jnz short exit16err
  285.         ret
  286. ;─────────────────────────────────────────────────────────────────────────────
  287. pregetlomem:                            ; Get low memory or abort
  288.         add eax,ds:_lomembase
  289.         mov ebx,ds:_lomemtop
  290.         cmp eax,ebx
  291.         ja short pregetlomema
  292.         mov ecx,eax
  293.         xchg eax,ds:_lomembase
  294.         sub ebx,ecx
  295.         cmp ebx,LOWMIN*1024
  296.         jb short pregetlomema
  297.         ret
  298. pregetlomema:
  299.         mov dx,offset errmsg1
  300. ;─────────────────────────────────────────────────────────────────────────────
  301. exit16err:                              ; Exit program with message
  302.         mov ah,9
  303.         int 21h
  304.         jmp exitrout
  305. ;-----------------------------------------------------------------------------
  306. exit:                                   ; Guess what???
  307.         mov ah,4ch
  308.         int 21h
  309. ;═════════════════════════════════════════════════════════════════════════════
  310. start16:                                ; Program begins here
  311.         cli
  312.         cld
  313.         push cs
  314.         pop ds
  315.  
  316.         call chek_processor             ; is it at least a 386¿
  317.  
  318.         mov ax,es                       ; set up a bunch of pointers
  319.         movzx eax,ax
  320.         shl eax,4
  321.         mov ds:_pspa,eax
  322.         mov eax,code16
  323.         shl eax,4
  324.         mov ds:_code16a,eax
  325.         or dword ptr ds:gdt32code16[2],eax
  326.         or dword ptr ds:gdt32data16[2],eax
  327.         mov ebx,code32
  328.         shl ebx,4
  329.         mov ds:_code32a,ebx
  330.         or dword ptr ds:gdt32code32[2],ebx
  331.         or dword ptr ds:gdt32data32[2],ebx
  332.         add dword ptr ds:c_gdt32addx[2],ebx
  333.         mov eax,codeend
  334.         shl eax,4
  335.         sub eax,ebx
  336.         mov ds:_lomembase,eax
  337.         mov ds:realstackbase,eax
  338.         movzx eax,word ptr es:[2]
  339.         shl eax,4
  340.         sub eax,ebx
  341.         mov ds:_lomemtop,eax
  342.  
  343.         mov eax,STAKLEN*16              ; get stack memory
  344.         call pregetlomem
  345.  
  346.         push es                         ; save PSP seg (DPMI chek kills ES)
  347.         pop fs
  348.  
  349.         mov ax,1687h                    ; chek for DPMI
  350.         int 2fh
  351.         or ax,ax
  352.         jz d_start
  353.  
  354.         call chek_VCPI                  ; chek for VCPI
  355.         jnc v_start
  356.  
  357.         call chek_V86                   ; chek for V86 mode
  358.  
  359.         mov ax,4300h                    ; chek for XMS
  360.         int 2fh
  361.         cmp al,80h
  362.         je x_start
  363.  
  364.         jmp c_start                     ; custom system start
  365. ;─────────────────────────────────────────────────────────────────────────────
  366. enableA20:                              ; hardware enable gate A20
  367.         xor ax,ax
  368.         mov fs,ax
  369.         dec ax
  370.         mov gs,ax
  371.         call testA20
  372.         je short enableA20done
  373.         in al,92h                       ; PS/2 A20 enable
  374.         or al,2
  375.         jmp short $+2
  376.         jmp short $+2
  377.         jmp short $+2
  378.         out 92h,al
  379.         call testA20
  380.         je short enableA20done
  381.         call enableA20o1                ; AT A20 enable
  382.         jnz short enableA20wait
  383.         mov al,0d1h
  384.         out 64h,al
  385.         call enableA20o1
  386.         jnz short enableA20wait
  387.         mov al,0dfh
  388.         out 60h,al
  389.         push offset enableA20wait
  390. enableA20o1:
  391.         mov ecx,20000h
  392. enableA20o1l:
  393.         jmp short $+2
  394.         jmp short $+2
  395.         jmp short $+2
  396.         in al,64h
  397.         test al,2
  398.         loopnz enableA20o1l
  399. enableA20done:
  400.         ret
  401. ;-----------------------------------------------------------------------------
  402. enableA20wait:                          ; wait for A20
  403.         mov al,36h
  404.         out 43h,al
  405.         xor al,al
  406.         out 40h,al
  407.         out 40h,al
  408.         mov cx,800h
  409. enableA20waitl0:
  410.         call testA20
  411.         je enableA20done
  412.         in al,40h
  413.         in al,40h
  414.         mov ah,al
  415. enableA20waitl1:
  416.         in al,40h
  417.         in al,40h
  418.         cmp al,ah
  419.         je enableA20waitl1
  420.         loop enableA20waitl0
  421.         mov dx,offset errmsg4
  422.         jmp exit16err
  423. ;-----------------------------------------------------------------------------
  424. testA20:                                ; Test for enabled A20
  425.         mov al,fs:[0]
  426.         mov ah,al
  427.         not al
  428.         mov gs:[10h],al
  429.         cmp ah,fs:[0]
  430.         mov fs:[0],ah
  431.         ret
  432. ;─────────────────────────────────────────────────────────────────────────────
  433. ; BL=low PIC val, BH=high PIC val
  434. setintslots:                            ; set int nums in table to PIC vals
  435.         mov edi,offset ds:intslottbl
  436.         mov cl,8
  437. setintslotsl0:
  438.         mov [di],bl
  439.         inc di
  440.         inc bl
  441.         dec cl
  442.         jnz setintslotsl0
  443.         mov cl,8
  444. setintslotsl1:
  445.         mov [di],bh
  446.         inc di
  447.         inc bh
  448.         dec cl
  449.         jnz setintslotsl1
  450.         ret
  451.  
  452. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  453. ; 16 bit DPMI system data
  454. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  455. d_errmsg0       db      'DPMI host is not 32bit!!!',7,'$'
  456. d_errmsg1       db      'Ran out of DPMI descriptors!!!',7,'$'
  457. d_errmsg2       db      'Couldn''t set DPMI descriptors as needed!!!',7,'$'
  458.  
  459. d_enterpmode    dw      ?,?             ; DPMI switch to pmode addx
  460. d_pspsel        dw      ?               ; stupid PSP selector
  461. d_oldenvsegsel  dw      ?               ; stupid selector we dont want
  462.  
  463. d_switchaddx    dd      ?               ; switch to pmode addx
  464. d_saveaddx      dd      ?               ; save/restore state addx
  465.  
  466. d_nintoff       dd      offset dp_irq0,offset dp_irq1,offset dp_irq2,offset dp_irq3
  467.                 dd      offset dp_irq4,offset dp_irq5,offset dp_irq6,offset dp_irq7
  468.                 dd      offset dp_irq8,offset dp_irq9,offset dp_irqa,offset dp_irqb
  469.                 dd      offset dp_irqc,offset dp_irqd,offset dp_irqe,offset dp_irqf
  470.                 dd      offset dp_int33,offset dp_int32,offset dp_int33,offset dp_int32
  471. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  472. ; 16 bit DPMI system code
  473. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  474. ;═════════════════════════════════════════════════════════════════════════════
  475. d_retreal:                              ; Return to real mode
  476.         mov ax,205h                     ; restore all int vektorz needed
  477.         mov edi,19
  478. d_retreall0:
  479.         mov bl,ds:intslottbl[edi]
  480.         lea ebp,[edi*2+edi]
  481.         mov edx,dword ptr ds:dp_ointbuf[ebp*2]
  482.         mov cx,word ptr ds:dp_ointbuf[ebp*2+4]
  483.         int 31h
  484.         sub di,1
  485.         jnc d_retreall0
  486.         jmp short d_exit
  487. ;─────────────────────────────────────────────────────────────────────────────
  488. d_exit16err:                            ; DPMI Exit with error message
  489.         mov ds:v86r_ds,code16
  490.         mov ds:v86r_ah,9
  491.         mov ax,300h
  492.         mov bx,21h
  493.         xor cx,cx
  494.         mov edi,offset ds:v86r_edi
  495.         push ds
  496.         pop es
  497.         int 31h
  498. ;─────────────────────────────────────────────────────────────────────────────
  499. d_exit:                                 ; DPMI exit to real mode
  500.         mov es,d_pspsel                 ; restore env selector
  501.         mov ax,d_oldenvsegsel
  502.         mov es:[2ch],ax
  503.         jmp exit
  504. ;═════════════════════════════════════════════════════════════════════════════
  505. d_start:                                ; Start in a crappy DPMI system
  506.         or ds:_sysbyte0,3               ; set system type DPMI byte
  507.  
  508.         test bl,1                       ; must be 32bit DPMI
  509.         mov dx,offset d_errmsg0
  510.         jz exit16err
  511.  
  512.         mov d_enterpmode[0],di          ; store enter addx
  513.         mov d_enterpmode[2],es
  514.         push word ptr fs:[2ch]          ; preserve old env seg
  515.  
  516.         movzx eax,si                    ; get mem for DPMI blok
  517.         shl eax,4
  518.         call pregetlomem
  519.         shr eax,4
  520.         add ax,code32
  521.         mov es,ax
  522.  
  523.         mov ax,1                        ; switch to pmode
  524.         call dword ptr d_enterpmode
  525.         cli                             ; I don't trust DPMI
  526.         mov dx,offset d_errmsg1
  527.         jc exit16err
  528.         mov ds:v86r_dx,dx               ; prepare for abort maybe
  529.         pop ax                          ; swap old env seg with selector
  530.         xchg ax,es:[2ch]
  531.         mov d_oldenvsegsel,ax
  532.         mov d_pspsel,es                 ; store stupid selectors
  533.         mov ds:data16sel,ds
  534.         mov ds:code16sel,cs
  535.         mov ds:code16off,offset d_retreal       ; set return to real mode addx
  536.         mov ds:_setirqvect,offset dp_setirqvect ; modify some crap
  537.         mov ds:_getirqvect,offset dp_getirqvect
  538.  
  539.         push ds                         ; no more need for PSP
  540.         pop es
  541.         mov ax,3                        ; get selector increment value
  542.         int 31h
  543.         mov bx,ax
  544.         xor ax,ax                       ; get 3 needed descriptors
  545.         mov cx,3
  546.         int 31h
  547.         jc d_exit16err
  548.  
  549.         mov si,ax                       ; set up descriptors
  550.         mov ds:_selcode,ax
  551.         lea ecx,[eax+ebx]
  552.         mov ds:_seldata,cx
  553.         lea ebp,[ecx+ebx]
  554.         mov ds:_selzero,bp
  555.         mov ds:v86r_dx,offset d_errmsg2
  556.         mov ax,0ch                      ; set descriptors from GDT
  557.         mov bx,si
  558.         mov edi,offset ds:gdt32code32
  559.         or byte ptr [edi+5],60h
  560.         int 31h
  561.         jc d_exit16err
  562.         mov bx,cx
  563.         mov edi,offset ds:gdt32data32
  564.         or byte ptr [edi+5],60h
  565.         int 31h
  566.         jc d_exit16err
  567.         mov bx,bp
  568.         mov edi,offset ds:gdt32zero32
  569.         or byte ptr [edi+5],60h
  570.         int 31h
  571.         jc d_exit16err
  572.  
  573.         mov es,cx                       ; ES, FS, and GS what they should be
  574.         mov fs,cx
  575.         mov gs,bp
  576.  
  577.         mov edi,ds:_lomembase           ; chek and get extended memory
  578.         mov eax,ds:_lomemtop
  579.         sub eax,edi
  580.         cmp eax,48
  581.         mov ds:v86r_dx,offset errmsg1
  582.         jb d_exit16err
  583.         mov ax,500h
  584.         int 31h
  585.         mov eax,es:[edi+14h]
  586.         cmp eax,-1
  587.         jne short d_startf0
  588.         mov eax,(EXTMIN+3) shr 2
  589. d_startf0:
  590.         shl eax,12
  591.         mov edx,eax
  592.         shr eax,10
  593.         cmp eax,EXTMIN
  594.         mov ds:v86r_dx,offset errmsg3
  595.         jb d_exit16err
  596.         or edx,edx
  597.         jz short d_startf1
  598.         mov cx,dx
  599.         shld ebx,edx,16
  600.         mov ax,501h
  601.         int 31h
  602.         mov ds:v86r_dx,offset errmsg5
  603.         jc d_exit16err
  604.         shl ebx,16
  605.         mov bx,cx
  606.         sub ebx,ds:_code32a
  607.         mov ds:_himembase,ebx
  608.         add ebx,edx
  609.         mov ds:_himemtop,ebx
  610. d_startf1:
  611.  
  612.         mov ax,305h                     ; get save/restore state addxs
  613.         int 31h
  614.         mov ds:dp_savelen,ax
  615.         mov dword ptr ds:dp_saveaddx[0],edi
  616.         mov word ptr ds:dp_saveaddx[4],si
  617.         mov word ptr d_saveaddx[0],cx
  618.         mov word ptr d_saveaddx[2],bx
  619.         mov ax,306h                     ; get switch mode addxs
  620.         int 31h
  621.         mov dword ptr ds:dp_switchaddx[0],edi
  622.         mov word ptr ds:dp_switchaddx[4],si
  623.         mov word ptr d_switchaddx[0],cx
  624.         mov word ptr d_switchaddx[2],bx
  625.  
  626.         mov ax,400h                     ; set IRQ handlers to PIC values
  627.         int 31h
  628.         xchg dl,dh
  629.         mov bx,dx
  630.         call setintslots
  631.  
  632.         mov ah,2                        ; backup and set all int vektorz
  633.         mov si,ds:_selcode
  634.         mov edi,19
  635. d_startl0:
  636.         mov bl,ds:intslottbl[edi]
  637.         mov al,4
  638.         int 31h
  639.         lea ebp,[edi*2+edi]
  640.         mov dword ptr ds:dp_ointbuf[ebp*2],edx
  641.         mov word ptr ds:dp_ointbuf[ebp*2+4],cx
  642.         mov al,5
  643.         mov edx,d_nintoff[edi*4]
  644.         mov cx,si
  645.         int 31h
  646.         sub di,1
  647.         jnc d_startl0
  648.  
  649.         mov ax,es                       ; set up needed regs & go on to 32bit
  650.         mov ss,ax
  651.         add esp,ds:realstackbase
  652.         mov ds,ax
  653.         push dword ptr cs:_selcode
  654.         push offset p_start
  655.         db 66h,0cbh             ; 32bit RETF
  656.  
  657. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  658. ; 16bit VCPI system data
  659. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  660. v_errmsg0       db      'Incompatible VCPI PIC mappings!!!',7,'$'
  661.  
  662. v_emmname       db      'EMMXXXX0',0    ; EMS device name
  663. v_emshandle     dw      ?               ; one page allocated to turn on
  664.  
  665. v_pagedirseg    dw      ?               ; seg of page directory
  666. v_pagebase      dw      0               ; first page of himem (*4)+1000h
  667. v_pagetop       dw      0               ; top page of himem (*4)+1000h
  668.  
  669. v_ss_cr3        dd      ?               ; new CR3 for pmode (physical)
  670. v_ss_gdtaddxptr dw      c_gdt32addx,0   ; ptr to GDT data for pmode
  671. v_ss_idtaddxptr dw      c_idt32addx,0   ; ptr to IDT data for pmode
  672. v_ss_ldtsel     dw      0               ; don't need no stinkin LDTs
  673. v_ss_trsel      dw      30h             ; task state segment selector
  674. v_ss_dest       dd      ?               ; start in pmode EIP
  675.                 dw      20h             ; start in pmode CS
  676. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  677. ; 16bit VCPI system code
  678. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  679. ;═════════════════════════════════════════════════════════════════════════════
  680. v_retreal:                              ; VCPI return to real mode
  681.         movzx edi,exitrout
  682.         mov esi,esp
  683.         sub esi,ds:realstackbase
  684.         mov cx,code16
  685. ;═════════════════════════════════════════════════════════════════════════════
  686. ; EDI=offset to jump to, ESI=real mode stack ptr, CX=real mode DS
  687. v_retreal0:                             ; VCPI go to real mode
  688.         sub esp,8
  689.         push ecx
  690.         push dword ptr ds:v86r_es
  691.         dw 06866h,codeend,0     ; PUSH dword codeend
  692.         push esi
  693.         pushfd
  694.         dw 06866h,code16,0      ; PUSH dword code16
  695.         push edi
  696.         mov ax,gs
  697.         mov ds,ax
  698.         mov ax,0de0ch
  699.         call cs:vp_vcpipmentry
  700. ;─────────────────────────────────────────────────────────────────────────────
  701. v_exit2:                                ; VCPI exit (clean up pages)
  702.         mov es,v_pagedirseg
  703.         mov si,v_pagebase
  704.         mov cx,v_pagetop
  705.         sub cx,si
  706.         jz short v_exit
  707. v_exit2l0:
  708.         mov edx,es:[si]
  709.         and dx,0f000h
  710.         mov ax,0de05h
  711.         int 67h
  712.         add si,4
  713.         sub cx,4
  714.         jnz v_exit2l0
  715. ;─────────────────────────────────────────────────────────────────────────────
  716. v_exit:                                 ; VCPI exit (clean up EMS page)
  717.         mov ah,45h
  718.         mov dx,v_emshandle
  719.         int 67h
  720.         jmp exit
  721. ;─────────────────────────────────────────────────────────────────────────────
  722. v_exiterr1:                             ; VCPI not enough low mem exit
  723.         mov dx,offset errmsg1
  724.         jmp exit16err
  725. ;═════════════════════════════════════════════════════════════════════════════
  726. v_start:                                ; start continues from VCPI
  727.         or ds:_sysbyte0,2               ; set system type VCPI byte
  728.         mov ds:code16off,offset v_retreal       ; VCPI return to real mode
  729.         mov c_idt32handler[48h],offset vp_int33 ; VCPI safe int handlers
  730.         mov c_idt32handler[4ch],offset vp_int32
  731.         mov ds:cp_v86irqintr[4],offset vp_int33f0 ; VCPI IRQ safe int routine
  732.         mov int32m0,VINT32              ; VCPI real INT32
  733.         mov exitrout,offset v_exit      ; set EMS cleanup exit
  734.  
  735.         mov ax,0de0ah                   ; get PIC mappings
  736.         int 67h
  737.         mov bh,cl
  738.         mov dx,offset v_errmsg0         ; chek for compatible PIC mapping
  739.         cmp bl,bh
  740.         je exit16err
  741.         cmp bl,30h
  742.         je exit16err
  743.         cmp bh,30h
  744.         je exit16err
  745.         mov ax,70h                      ; compatible, get highest needed num
  746.         cmp al,bl
  747.         ja short v_startf1
  748.         mov al,bl
  749. v_startf1:
  750.         cmp al,bh
  751.         ja short v_startf2
  752.         mov al,bh
  753. v_startf2:
  754.         add al,7
  755.         mov c_numofintvects,al
  756.         lea eax,[eax*8+7]               ; set limit of IDT
  757.         mov c_idt32addx,ax
  758.         call setintslots                ; set int slots needed
  759.         movzx eax,ax
  760.         add eax,2068h+1
  761.         call pregetlomem                ; allocate TSS, IO bitmap, and IDT
  762.         mov ds:cp_tssesp0ptr,eax
  763.         mov eax,ds:_code16a             ; adjust mode switch structure
  764.         add dword ptr v_ss_gdtaddxptr,eax
  765.         add dword ptr v_ss_idtaddxptr,eax
  766.  
  767.         mov exitrout,offset v_exit2     ; set VCPI cleanup exit
  768.  
  769.         mov eax,ds:_lomembase           ; align lomem base on a page
  770.         mov ebx,ds:_code32a
  771.         add ebx,eax
  772.         lea ecx,[ebx+0fffh]
  773.         and ecx,0fffff000h
  774.         sub ebx,ecx
  775.         sub eax,ebx
  776.         mov ds:_lomembase,eax
  777.         mov ebp,ds:_lomemtop            ; get available low memory
  778.         sub ebp,eax
  779.         sub ebp,LOWMIN*1024             ; die if not enough
  780.         jc v_exiterr1
  781.         cmp ebp,8192
  782.         jb v_exiterr1
  783.  
  784.         shld eax,ecx,28                 ; get segment and clear all pages
  785.         mov v_pagedirseg,ax
  786.         mov es,ax
  787.         xor di,di
  788.         mov cx,2048
  789.         xor eax,eax
  790.         rep stos dword ptr es:[di]
  791.         mov di,1000h                    ; get VCPI pmode interface
  792.         mov esi,offset ds:gdt32vcpi
  793.         mov ax,0de01h
  794.         int 67h
  795.         mov dword ptr ds:vp_vcpipmentry,ebx
  796.  
  797.         mov v_pagebase,di               ; set up and go through allocation
  798.         mov v_pagetop,di
  799.         movzx eax,di
  800.         sub eax,1000h
  801.         shl eax,10
  802.         mov ebp,ds:_code32a
  803.         sub eax,ebp
  804.         mov ds:_himembase,eax
  805.         mov ebx,8192
  806. v_startl2:
  807.         mov ax,0de04h
  808.         int 67h
  809.         or ah,ah
  810.         jnz short v_startl2d
  811.         test di,0fffh
  812.         jnz short v_startf4
  813.         add ebx,4096
  814.         cmp ebx,ebp
  815.         ja v_exiterr1
  816. v_startf4:
  817.         and dx,0f000h
  818.         or dl,7
  819.         mov es:[di],edx
  820.         add di,4
  821.         jnc v_startl2
  822. v_startl2d:
  823.         mov v_pagetop,di
  824.         lea si,[di-1000h]
  825.         movzx eax,si
  826.         shl eax,10
  827.         sub eax,ebp             ; EBP=_code32a
  828.         mov ds:_himemtop,eax
  829.         sub di,v_pagebase
  830.         cmp di,EXTMIN
  831.         mov dx,offset errmsg3
  832.         jb exit16err
  833.         add ds:_lomembase,ebx
  834.  
  835.         movzx ebx,v_pagedirseg          ; set up physical addresses
  836.         shr ebx,8
  837.         mov eax,es:[ebx*4+1000h]
  838.         mov v_ss_cr3,eax
  839.         xor di,di
  840. v_startl3:
  841.         inc ebx
  842.         mov eax,es:[ebx*4+1000h]
  843.         and ax,0f000h
  844.         or al,7
  845.         stos dword ptr es:[di]
  846.         sub si,1000h
  847.         ja v_startl3
  848.  
  849.         mov edi,offset c_startf1        ; offset to jump to in pmode
  850.         mov ebx,ds:cp_tssesp0ptr
  851.         jmp v_switchtopmode             ; duh?
  852.  
  853. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  854. ; 16 bit XMS system data
  855. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  856. x_calladdx      dd      ?               ; XMS driver addx
  857. x_handle        dw      ?               ; XMS handle of extended memory
  858. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  859. ; 16 bit XMS system code
  860. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  861. ;─────────────────────────────────────────────────────────────────────────────
  862. x_exit:                                 ; XMS exit (clean up allocation)
  863.         mov ax,cs
  864.         mov ds,ax
  865.         mov dx,x_handle
  866.         mov ah,0dh
  867.         call x_calladdx
  868.         mov ah,0ah
  869.         call x_calladdx
  870.         jmp exit
  871. ;─────────────────────────────────────────────────────────────────────────────
  872. x_exiterr5:                             ; exit with error message 5
  873.         mov dx,offset errmsg5
  874.         jmp exit16err
  875. ;═════════════════════════════════════════════════════════════════════════════
  876. x_start:                                ; start in an XMS system
  877.         or ds:_sysbyte0,1               ; set system type XMS byte
  878.  
  879.         mov ax,4310h                    ; get XMS driver addx
  880.         int 2fh
  881.         mov word ptr x_calladdx[0],bx
  882.         mov word ptr x_calladdx[2],es
  883.  
  884.         mov ah,3                        ; XMS enable A20
  885.         call x_calladdx
  886.         or ax,ax
  887.         mov dx,offset errmsg4
  888.         jz exit16err
  889.  
  890.         mov ah,8                        ; chek and get extended memory
  891.         call x_calladdx
  892.         sub ax,64
  893.         jnc short x_startf0
  894.         xor ax,ax
  895. x_startf0:
  896.         cmp ax,EXTMIN
  897.         mov dx,offset errmsg3
  898.         jb exit16err
  899.         mov dx,ax
  900.         movzx ecx,ax
  901.         shl ecx,10
  902.         mov ah,9
  903.         call x_calladdx
  904.         or ax,ax
  905.         jz x_exiterr5
  906.         mov x_handle,dx
  907.         mov exitrout,offset x_exit
  908.         mov ah,0ch
  909.         call x_calladdx
  910.         or ax,ax
  911.         jz x_exiterr5
  912.         shrd eax,edx,16
  913.         mov ax,bx
  914.         sub eax,ds:_code32a
  915.         mov ds:_himembase,eax
  916.         add eax,ecx
  917.         mov ds:_himemtop,eax
  918.  
  919.         jmp c_startf0                   ; go on to custom start
  920.  
  921. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  922. ; 16 bit custom system data
  923. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  924. c_idt16addx     dw      3ffh, 0,0       ; default real mode IDT addx&limit
  925. c_idt32addx     dw      3bfh, ?,?       ; 32bit IDT addx&limit
  926. c_gdt32addx     dw      04fh            ; 32bit GDT addx&limit
  927.                 dd      offset gdt32    ;
  928.  
  929. c_numofintvects db      77h             ; number of int vects needed -1
  930. c_idt32handler  dd      offset cp_irq0,offset cp_irq1,offset cp_irq2,offset cp_irq3
  931.                 dd      offset cp_irq4,offset cp_irq5
  932.                 dd      offset cp_irq6,offset cp_irq7,offset cp_irq8,offset cp_irq9
  933.                 dd      offset cp_irqa,offset cp_irqb
  934.                 dd      offset cp_irqc,offset cp_irqd,offset cp_irqe,offset cp_irqf
  935.                 dd      offset cp_int35,offset cp_int34,offset cp_int33,offset cp_int32,offset cp_int31
  936.                 dd      offset cp_exc0,offset cp_exc1,offset cp_exc2,offset cp_exc3
  937.                 dd      offset cp_exc4,offset cp_exc5
  938.                 dd      offset cp_exc6,offset cp_exc7,offset cp_exc8,offset cp_exc9
  939.                 dd      offset cp_exca,offset cp_excb
  940.                 dd      offset cp_excc,offset cp_excd,offset cp_exce
  941. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  942. ; 16 bit custom system code
  943. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  944. ;═════════════════════════════════════════════════════════════════════════════
  945. c_irqreal:                              ; real mode IRQ
  946.         pushf
  947.         push cs
  948.         push offset icreald2
  949.         jmp icreal
  950. ;-----------------------------------------------------------------------------
  951. c_retreal1:                             ; load some real mode stuff & exit
  952.         mov ax,codeend
  953.         mov ss,ax
  954.         mov esp,STAKLEN*10h
  955.         jmp exitrout
  956. ;═════════════════════════════════════════════════════════════════════════════
  957. c_retreal0:                             ; load real mode IDT and set PE=0
  958.         mov ax,28h
  959.         mov ds,ax
  960.         mov es,ax
  961.         mov fs,ax
  962.         mov gs,ax
  963.         mov ss,ax
  964.         lidt fword ptr c_idt16addx
  965.         mov eax,cr0
  966.         and al,0feh
  967.         mov cr0,eax
  968.         db 0eah                 ; JMP FAR PTR c_retreal0m0
  969. c_retreal0m0    dw c_sicreal,code16
  970. ;-----------------------------------------------------------------------------
  971. c_sicreal:                              ; safe real mode int or call
  972.         mov ax,codeend
  973.         mov ss,ax
  974.         mov ds,cs:v86r_ds
  975.         mov es,cs:v86r_es
  976.         db 0eah                 ; JMP FAR PTR c_sicrealm0
  977. c_sicrealm0     dw      ?,code16;
  978. ;═════════════════════════════════════════════════════════════════════════════
  979. c_retreal:                              ; return to real mode
  980.         mov c_retreal0m0,offset c_retreal1
  981.         mov esp,STAKLEN*10h
  982.         jmp c_retreal0
  983. ;═════════════════════════════════════════════════════════════════════════════
  984. c_start:                                ; custom only start
  985.         call enableA20                  ; enable that stupid A20 thingy
  986.  
  987.         mov ah,88h                      ; chek and get extended mem
  988.         int 15h
  989.         cmp ax,EXTMIN
  990.         mov dx,offset errmsg3
  991.         jb exit16err
  992.         movzx eax,ax
  993.         shl eax,10
  994.         mov ebx,100000h
  995.         sub ebx,ds:_code32a
  996.         mov ds:_himembase,ebx
  997.         add eax,ebx
  998.         mov ds:_himemtop,eax
  999. ;═════════════════════════════════════════════════════════════════════════════
  1000. c_startf0:                              ; start continues from custom or XMS
  1001.         mov int32m0,CINT32              ; raw/XMS real INT32
  1002.         mov eax,2428h                   ; allocate TSS, IO bitmap, and IDT
  1003.         call pregetlomem
  1004.         mov ebx,eax
  1005.  
  1006.         lgdt fword ptr c_gdt32addx      ; switch to pmode
  1007.         mov eax,cr0
  1008.         or al,1
  1009.         mov cr0,eax
  1010.         db 0eah
  1011.         dw $+4,20h
  1012. ;-----------------------------------------------------------------------------
  1013. ; EBX->TSS
  1014. c_startf1:                              ; in 16bit pmode
  1015.         mov ax,28h                      ; set up segregs
  1016.         mov ds,ax
  1017.         mov al,18h
  1018.         mov gs,ax
  1019.         mov al,10h
  1020.         mov es,ax
  1021.         mov fs,ax
  1022.         mov ss,ax
  1023.         mov esp,STAKLEN*16
  1024.         add esp,ds:realstackbase
  1025.  
  1026.         mov word ptr v_ss_dest[4],8     ; VCPI enter 32bit pmode from now on
  1027.         lea eax,[ebx+4]                 ; addx of ESP0 in TSS
  1028.         mov ds:cp_tssesp0ptr,eax
  1029.         mov ebp,ds:_code32a             ; TSS location in mem to GDT
  1030.         lea eax,[ebx+ebp]
  1031.         mov ecx,offset ds:gdt32task     ; set up task
  1032.         or dword ptr ds:[ecx+2],eax
  1033.         mov byte ptr ds:[ecx+5],89h
  1034.         mov cx,30h
  1035.         ltr cx
  1036.         add eax,2068h                   ; set up IDT
  1037.         mov ecx,offset c_idt32addx
  1038.         mov dword ptr [ecx+2],eax
  1039.         lidt fword ptr [ecx]
  1040.  
  1041.         mov dword ptr es:[ebx+8],10h    ; set up TSS stuff (EBX->TSS)
  1042.         mov edi,104
  1043.         mov es:[ebx+102],di
  1044.         mov word ptr es:[ebx+100],0
  1045.         add edi,ebx                     ; fill IO bitmap with 0
  1046.         xor eax,eax
  1047.         mov ecx,800h
  1048.         rep stos dword ptr es:[edi]
  1049.  
  1050.         mov ds:cp_idt32ptr,edi          ; set up blank IDT entries
  1051.         movzx esi,c_numofintvects
  1052. c_startl0:
  1053.         mov dword ptr es:[edi+esi*8],80000h+offset cp_excf
  1054.         mov dword ptr es:[edi+esi*8+4],8e00h
  1055.         sub si,1
  1056.         jnc c_startl0
  1057.         mov si,23h                      ; necessary IDT entries
  1058. c_startl1:
  1059.         movzx ebp,ds:intslottbl[esi]
  1060.         mov eax,c_idt32handler[esi*4]
  1061.         cmp bp,13
  1062.         jne short c_startl1c
  1063.         mov ds:cp_int13vect,eax
  1064.         mov eax,offset cp_excd
  1065. c_startl1c:
  1066.         mov es:[edi+ebp*8],ax
  1067.         sub si,1
  1068.         jnc c_startl1
  1069.  
  1070.         mov edi,offset p_start          ; set up regs & go on to 32bit
  1071.         mov ax,10h
  1072.         mov ds,ax
  1073. ;-----------------------------------------------------------------------------
  1074. c_gotopmode:                            ; jump to 32bit pmode
  1075.         pushfd                          ; set eflags: NT=0, IOPL=3
  1076.         pop eax
  1077.         and ah,0bfh
  1078.         or ah,30h
  1079.         push eax
  1080.         popfd
  1081.         dw 6866h,8,0            ; PUSH dword 8
  1082.         push edi
  1083.         db 66h,0cbh             ; 32bit RETF
  1084.  
  1085. code16  ends
  1086.  
  1087. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  1088. ; 32bit pmode code
  1089. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  1090. code32  segment para public use32
  1091.         assume cs:code32, ds:code32
  1092.         org 0
  1093.  
  1094. extrn   _main:near
  1095.  
  1096. public  _exit, _ret, _getmem, _getlomem, _gethimem, _lomemsize, _himemsize
  1097. public  _getirqmask, _setirqmask
  1098.  
  1099. public  v86r_eax, v86r_ebx, v86r_ecx, v86r_edx, v86r_esi, v86r_edi, v86r_ebp
  1100. public  v86r_ax, v86r_bx, v86r_cx, v86r_dx, v86r_si, v86r_di, v86r_bp
  1101. public  v86r_al, v86r_ah, v86r_bl, v86r_bh, v86r_cl, v86r_ch, v86r_dl, v86r_dh
  1102. public  v86r_ds, v86r_es, v86r_fs, v86r_gs
  1103. public  _selcode, _seldata, _selzero, _lomembase, _lomemtop, _himembase
  1104. public  _himemtop, _pspa, _code16a, _code32a, _getirqvect, _setirqvect
  1105. public  _sysbyte0, _irqmode
  1106. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1107. ; 32 bit common system data
  1108. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1109. _lomembase      dd      ?               ; low mem base for allocation
  1110. _lomemtop       dd      ?               ; top of low mem
  1111. _himembase      dd      0               ; high mem base for allocation
  1112. _himemtop       dd      0               ; top of high mem
  1113. _pspa           dd      ?               ; offset of start of PSP from 0
  1114. _code16a        dd      ?               ; offset of start of 16bit code from 0
  1115. _code32a        dd      ?               ; offset of start of 32bit code from 0
  1116. _selcode        dw      8               ; code segment selector
  1117. _seldata        dw      10h             ; data segment alias for code
  1118. _selzero        dw      18h             ; data segment starting at 0:0
  1119. _irqmode        dw      0ffffh          ; IRQ mode bits: 0=normal, 1=safe
  1120.                 db      0ffh            ; misc byte, has to follow _irqmode
  1121. _sysbyte0       db      0               ; system bits:
  1122.                                         ;  0-1: 0=raw, 1=XMS, 2=VCPI, 3=DPMI
  1123.  
  1124. _getirqvect     dd      cp_getirqvect   ; get IRQ handler offset routine addx
  1125. _setirqvect     dd      cp_setirqvect   ; set IRQ handler offset routine addx
  1126.  
  1127. gdt32           dq      0
  1128. gdt32code32     db      0ffh,0ffh,0,0,0,9ah,0cfh,0
  1129. gdt32data32     db      0ffh,0ffh,0,0,0,92h,0cfh,0
  1130. gdt32zero32     db      0ffh,0ffh,0,0,0,92h,0cfh,0
  1131. gdt32code16     db      0ffh,0ffh,0,0,0,9ah,0,0
  1132. gdt32data16     db      0ffh,0ffh,0,0,0,92h,0,0
  1133. gdt32task       db      0ffh,0ffh,0,0,0,89h,0,0
  1134. gdt32vcpi       dq      3 dup(?)
  1135.  
  1136. v86r_edi        label   dword           ; vregs for pmode<>real communication
  1137. v86r_di         dw      ?, ?            ;  needz to stay this way cuz its a
  1138. v86r_esi        label   dword           ;  stupid DPMI structure thingy
  1139. v86r_si         dw      ?, ?
  1140. v86r_ebp        label   dword
  1141. v86r_bp         dw      ?, ?
  1142.                 dd      0
  1143. v86r_ebx        label   dword
  1144. v86r_bx         label   word
  1145. v86r_bl         db      ?
  1146. v86r_bh         db      ?, ?,?
  1147. v86r_edx        label   dword
  1148. v86r_dx         label   word
  1149. v86r_dl         db      ?
  1150. v86r_dh         db      ?, ?,?
  1151. v86r_ecx        label   dword
  1152. v86r_cx         label   word
  1153. v86r_cl         db      ?
  1154. v86r_ch         db      ?, ?,?
  1155. v86r_eax        label   dword
  1156. v86r_ax         label   word
  1157. v86r_al         db      ?
  1158. v86r_ah         db      ?, ?,?
  1159. v86r_flags      dw      ?
  1160. v86r_es         dw      ?
  1161. v86r_ds         dw      ?
  1162. v86r_fs         dw      ?
  1163. v86r_gs         dw      ?
  1164.                 dd      0,0
  1165.  
  1166. oint1bvect      dd      ?               ; old real int 1bh vektor (ctrl+break)
  1167. oint32vect      dd      ?               ; old real int 32h vector
  1168. oirqmask        dw      ?               ; old port 21h and 0a1h masks
  1169. intslottbl      db      8,9,0ah,0bh,0ch,0dh,0eh,0fh,70h,71h,72h,73h,74h,75h,76h,77h
  1170.                 db      35h,34h,33h,32h,31h,0,1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh
  1171.  
  1172. code16off       dw      c_retreal       ; offset in 16bit of exit function
  1173. code16sel       dw      20h             ; 16bit pmode code selector
  1174. data16sel       dw      28h             ; 16bit pmode data selector
  1175.  
  1176. nextmodestack   dw      (STAKLEN-STAKSAFE)*16   ; stack for next mode switch
  1177. realstackbase   dd      ?               ; linear ptr to beginning of codeend
  1178.  
  1179. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1180. ; 32 bit common system code
  1181. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1182. ;═════════════════════════════════════════════════════════════════════════════
  1183. p_cpmode2:                              ; call pmode from V86
  1184.         mov gs,cx
  1185.         mov cl,10h
  1186.         mov ds,cx
  1187.         mov es,cx
  1188.         mov fs,cx
  1189.         sub nextmodestack,STAKSAFE*16
  1190.         push p_cpmodem2
  1191.         mov p_cpmodem2,V86CPMODED
  1192.         mov eax,[esp+22]
  1193.         mov p_cpmodem0,eax
  1194.         mov al,[esp+43]
  1195.         shr al,1
  1196.         and al,1
  1197.         add al,0fah
  1198.         mov p_cpmodem1,al
  1199.         jmp short p_cpmode
  1200. ;═════════════════════════════════════════════════════════════════════════════
  1201. p_cpmode1:                              ; call pmode, load all
  1202.         mov esp,ebx
  1203.         mov ax,10h
  1204.         mov ds,ax
  1205.         mov es,ax
  1206.         mov ss,ax
  1207. ;-----------------------------------------------------------------------------
  1208. p_cpmode0:                              ; call pmode, load FS and GS
  1209.         mov fs,_seldata
  1210.         mov gs,_selzero
  1211. ;-----------------------------------------------------------------------------
  1212. p_cpmode:                               ; call pmode routine from real
  1213.         push offset p_cpmoded
  1214.         cld
  1215.         mov eax,v86r_eax
  1216.         mov ecx,v86r_ecx
  1217.         mov edx,v86r_edx
  1218.         mov ebx,v86r_ebx
  1219.         mov esi,v86r_esi
  1220.         mov edi,v86r_edi
  1221.         mov ebp,v86r_ebp
  1222.         db 68h                  ; PUSH destination address
  1223. p_cpmodem0      dd      ?       ;
  1224. p_cpmodem1      db      ?       ; CLI or STI
  1225.         ret
  1226. ;-----------------------------------------------------------------------------
  1227. p_cpmoded:                              ; call to pmode done
  1228.         cli
  1229.         pushf
  1230.         pop v86r_flags
  1231.         mov v86r_eax,eax
  1232.         mov v86r_ecx,ecx
  1233.         mov v86r_edx,edx
  1234.         mov v86r_ebx,ebx
  1235.         mov v86r_esi,esi
  1236.         mov v86r_edi,edi
  1237.         mov v86r_ebp,ebp
  1238.         mov ecx,_code16a
  1239. p_cpmodem2        label word            ; return to real, modifiable to JMP
  1240. ;-----------------------------------------------------------------------------
  1241.         movzx ebx,gs:savedstakoff[ecx]  ; DPMI return to real mode
  1242.         mov dx,gs:savedstakseg[ecx]
  1243.         mov ax,code16
  1244.         mov cx,dx
  1245.         mov si,ax
  1246.         mov edi,offset int32d0
  1247.         jmp dp_switchaddx
  1248. ;-----------------------------------------------------------------------------
  1249. VCPMODED=(($-(p_cpmodem2+2))shl 8)+0ebh
  1250. p_cpmoded2:                             ; VCPI done with pmode
  1251.         movzx esi,gs:savedstakoff[ecx]
  1252.         mov cx,code16
  1253.         mov edi,offset int32d1
  1254.         db 0eah                 ; 16bit JMP FAR 20h:v_retreal0
  1255.         dw v_retreal0,0,20h     ;
  1256. ;-----------------------------------------------------------------------------
  1257. CCPMODED=(($-(p_cpmodem2+2))shl 8)+0ebh
  1258. p_cpmoded3:                             ; raw/XMS done with pmode
  1259.         mov gs:c_retreal0m0[ecx],offset int32d3
  1260.         db 0eah                 ; 16bit JMP FAR 20h:c_retreal0
  1261.         dw c_retreal0,0,20h     ;
  1262. ;-----------------------------------------------------------------------------
  1263. if ($-(p_cpmodem2+2)) gt 127
  1264.   err
  1265. endif
  1266. V86CPMODED=(($-(p_cpmodem2+2))shl 8)+0ebh
  1267. p_cpmoded4:                             ; V86 done with pmode
  1268.         pop p_cpmodem2
  1269.         jmp cp_int3_d3
  1270. ;═════════════════════════════════════════════════════════════════════════════
  1271. p_start:                                ; common 32bit start
  1272.         mov eax,gs:[1bh*4]              ; neutralize crtl+break
  1273.         mov oint1bvect,eax
  1274.         db 65h,67h,0c7h,6       ; MOV DWORD PTR GS:[1bh*4],code16:nullint
  1275.         dw 1bh*4,nullint,code16 ;
  1276.         mov eax,gs:[32h*4]              ; set up for new real mode INT32
  1277.         mov oint32vect,eax
  1278.         db 65h,67h,0c7h,6       ; MOV DWORD PTR GS:[32h*4],code16:int32
  1279.         dw 32h*4,int32,code16   ;
  1280.         in al,21h                       ; save old PIC masks
  1281.         mov ah,al
  1282.         in al,0a1h
  1283.         mov oirqmask,ax
  1284.         jmp _main                       ; go to main code
  1285.  
  1286. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1287. ; Allocate any mem, (first cheks low, then high)
  1288. ; In:
  1289. ;   EAX - size requested
  1290. ; Out:
  1291. ;   CF=0 - memory allocated
  1292. ;   CF=1 - not enough mem
  1293. ;   EAX - linear pointer to mem or ?
  1294. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1295. _getmem:
  1296.         push eax
  1297.         call _getlomem
  1298.         jnc short getmemd
  1299.         pop eax
  1300.         jmp short _gethimem
  1301. getmemd:
  1302.         add esp,4
  1303. _ret:                                   ; generic RET instruction
  1304.         ret
  1305. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1306. ; Allocate some low mem
  1307. ; In:
  1308. ;   EAX - size requested
  1309. ; Out:
  1310. ;   CF=0 - memory allocated
  1311. ;   CF=1 - not enough mem
  1312. ;   EAX - linear pointer to mem or ?
  1313. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1314. _getlomem:
  1315.         add eax,_lomembase
  1316.         cmp eax,_lomemtop
  1317.         ja short getmemerr
  1318.         xchg eax,_lomembase
  1319.         clc
  1320.         ret
  1321. getmemerr:
  1322.         stc
  1323.         ret
  1324. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1325. ; Allocate some high mem
  1326. ; In:
  1327. ;   EAX - size requested
  1328. ; Out:
  1329. ;   CF=0 - memory allocated
  1330. ;   CF=1 - not enough mem
  1331. ;   EAX - linear pointer to mem or ?
  1332. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1333. _gethimem:
  1334.         add eax,_himembase
  1335.         cmp eax,_himemtop
  1336.         ja short getmemerr
  1337.         xchg eax,_himembase
  1338.         clc
  1339.         ret
  1340. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1341. ; Get amount of free low mem
  1342. ; Out:
  1343. ;   EAX - number of bytes free
  1344. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1345. _lomemsize:
  1346.         mov eax,_lomemtop
  1347.         sub eax,_lomembase
  1348.         ret
  1349. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1350. ; Get amount of free high mem
  1351. ; Out:
  1352. ;   EAX - number of bytes free
  1353. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1354. _himemsize:
  1355.         mov eax,_himemtop
  1356.         sub eax,_himembase
  1357.         ret
  1358. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1359. ; Get status of IRQ mask bit
  1360. ; In:
  1361. ;   BL - IRQ num (0-15)
  1362. ; Out:
  1363. ;   AL - status: 0=enabled, 1=disabled
  1364. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1365. _getirqmask:
  1366.         push ax
  1367.         in al,0a1h
  1368.         mov ah,al
  1369.         in al,21h
  1370.         xchg cl,bl
  1371.         shr ax,cl
  1372.         xchg cl,bl
  1373.         and al,1
  1374.         mov [esp],al
  1375.         pop ax
  1376.         ret
  1377. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1378. ; Set status of IRQ mask bit
  1379. ; In:
  1380. ;   BL - IRQ num (0-15)
  1381. ;   AL - status: 0=enabled, 1=disabled
  1382. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1383. _setirqmask:
  1384.         push ax bx cx dx
  1385.         mov cl,bl
  1386.         mov bx,0fffeh
  1387.         movzx dx,al
  1388.         rol bx,cl
  1389.         shl dx,cl
  1390.         in al,0a1h
  1391.         mov ah,al
  1392.         in al,21h
  1393.         and ax,bx
  1394.         or ax,dx
  1395.         out 21h,al
  1396.         mov al,ah
  1397.         out 0a1h,al
  1398.         pop dx cx bx ax
  1399.         ret
  1400. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1401. ; Exit to real mode
  1402. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1403. _exit:
  1404.         cli
  1405.         mov eax,oint1bvect              ; restore ctrl+break
  1406.         mov gs:[1bh*4],eax
  1407.         mov eax,oint32vect              ; restore real mode int 32h vector
  1408.         mov gs:[32h*4],eax
  1409.         mov ax,oirqmask                 ; restore PIC masks
  1410.         out 0a1h,al
  1411.         mov al,ah
  1412.         out 21h,al
  1413.         push code16sel                  ; go to 16bit pmode exit code
  1414.         push code16off
  1415.         mov ds,data16sel
  1416.         db 66h,0cbh             ; 16bit RETF
  1417.  
  1418. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1419. ; 32 bit DPMI system data
  1420. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1421. dp_switchaddx   df      ?               ; switch to real mode addx
  1422. dp_saveaddx     df      ?               ; save/restore state addx
  1423. dp_savelen      dw      0,0             ; length of state buffer
  1424. dp_savedstaksel dw      ?               ; current saved stack selector
  1425.  
  1426. dp_ointbuf      df      20 dup(?)       ; saved interrupt addx buffer
  1427. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1428. ; 32 bit DPMI system code
  1429. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1430. ;═════════════════════════════════════════════════════════════════════════════
  1431. dp_int32:                               ; DPMI INT32/34: CX:DX=seg:off
  1432.         pushad
  1433.         shl ecx,16
  1434.         mov cx,dx
  1435.         mov bp,offset callreal
  1436.         mov dl,1
  1437.         jmp short dp_int3_
  1438. ;═════════════════════════════════════════════════════════════════════════════
  1439. dp_int33:                               ; DPMI INT33/35: AL=int num
  1440.         pushad
  1441.         movzx eax,al
  1442.         mov ecx,gs:[eax*4]
  1443.         mov bp,offset intreal
  1444.         xor dl,dl
  1445. ;-----------------------------------------------------------------------------
  1446. dp_int3_:                               ; DPMI int or call to real mode
  1447.         mov ax,900h
  1448.         int 31h
  1449.         push ax
  1450.         and al,dl
  1451.         add al,0fah
  1452.         mov ebx,_code16a
  1453.         mov gs:icrealm0[ebx],al
  1454.         mov gs:icrealm1[ebx],ecx
  1455.         push cp_savedstakoff
  1456.         push dp_savedstaksel
  1457.         movzx ebx,nextmodestack
  1458.         lea eax,[ebx-STAKSAFE*16]
  1459.         mov nextmodestack,ax
  1460.         mov ax,ss
  1461.         mov es,ax
  1462.         sub esp,dword ptr dp_savelen
  1463.         mov edi,esp
  1464.         xor al,al
  1465.         call dp_saveaddx
  1466.         mov cp_savedstakoff,esp
  1467.         mov dp_savedstaksel,ss
  1468.         mov dx,codeend
  1469.         mov ax,v86r_ds
  1470.         mov cx,v86r_es
  1471.         movzx edi,bp
  1472.         mov si,code16
  1473.         jmp dp_switchaddx
  1474. ;-----------------------------------------------------------------------------
  1475. dp_int3_d:                              ; done with real mode int or call
  1476.         mov edi,esp
  1477.         mov al,1
  1478.         call dp_saveaddx
  1479.         add esp,dword ptr dp_savelen
  1480.         pop dp_savedstaksel
  1481.         pop cp_savedstakoff
  1482.         add nextmodestack,STAKSAFE*16
  1483.         mov bx,v86r_flags
  1484.         pop ax
  1485.         int 31h
  1486.         mov ax,ds
  1487.         mov es,ax
  1488.         mov fs,ax
  1489.         mov gs,_selzero
  1490.         jmp cp_int3_d2
  1491. ;═════════════════════════════════════════════════════════════════════════════
  1492. ; DPMI IRQ redirectors (needed to make all IRQ vector selectors = CS)
  1493. dp_irq0:
  1494.         jmp cs:dp_ointbuf[0]
  1495. dp_irq1:
  1496.         jmp cs:dp_ointbuf[6]
  1497. dp_irq2:
  1498.         jmp cs:dp_ointbuf[12]
  1499. dp_irq3:
  1500.         jmp cs:dp_ointbuf[18]
  1501. dp_irq4:
  1502.         jmp cs:dp_ointbuf[24]
  1503. dp_irq5:
  1504.         jmp cs:dp_ointbuf[30]
  1505. dp_irq6:
  1506.         jmp cs:dp_ointbuf[36]
  1507. dp_irq7:
  1508.         jmp cs:dp_ointbuf[42]
  1509. dp_irq8:
  1510.         jmp cs:dp_ointbuf[48]
  1511. dp_irq9:
  1512.         jmp cs:dp_ointbuf[54]
  1513. dp_irqa:
  1514.         jmp cs:dp_ointbuf[60]
  1515. dp_irqb:
  1516.         jmp cs:dp_ointbuf[66]
  1517. dp_irqc:
  1518.         jmp cs:dp_ointbuf[72]
  1519. dp_irqd:
  1520.         jmp cs:dp_ointbuf[78]
  1521. dp_irqe:
  1522.         jmp cs:dp_ointbuf[84]
  1523. dp_irqf:
  1524.         jmp cs:dp_ointbuf[90]
  1525.  
  1526. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1527. ; DPMI get IRQ handler offset
  1528. ; In:
  1529. ;   BL - IRQ num (0-0fh)
  1530. ; Out:
  1531. ;   EDX - offset of IRQ handler
  1532. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1533. dp_getirqvect:
  1534.         push ax ebx cx
  1535.         movzx ebx,bl
  1536.         mov bl,intslottbl[ebx]
  1537.         mov ax,204h
  1538.         int 31h
  1539.         pop cx ebx ax
  1540.         ret
  1541. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1542. ; DPMI set IRQ handler offset
  1543. ; In:
  1544. ;   BL - IRQ num (0-0fh)
  1545. ;   EDX - offset of IRQ handler
  1546. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1547. dp_setirqvect:
  1548.         push ax ebx cx
  1549.         movzx ebx,bl
  1550.         mov bl,intslottbl[ebx]
  1551.         mov cx,cs
  1552.         mov ax,205h
  1553.         int 31h
  1554.         pop cx ebx ax
  1555.         ret
  1556.  
  1557. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1558. ; 32 bit custom/XMS/VCPI system data
  1559. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1560. vp_vcpipmentry  df      3800000000h     ; VCPI entry point in pmode
  1561.  
  1562. cp_tssesp0ptr   dd      0               ; ptr to ESP0 in TSS, or null in VCPI
  1563. cp_idt32ptr     dd      ?               ; ptr to 32bit IDT
  1564. cp_int13vect    dd      0               ; interrupt vektor 13 ptr
  1565. cp_validirqesp  dd      0               ; valid IRQ ESP value for exc 13
  1566.  
  1567. cp_v86irqintr   dd      cp_int35f1,cp_int33f0   ; IRQ int call routines
  1568. cp_v86irqnum    db      ?               ; IRQ num for V86 mode
  1569. cp_v86irqmode   db      ?               ; IRQ mode for V86 mode (safe/norm)
  1570. cp_savedstakoff dd      ?               ; current saved stack offset
  1571. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1572. ; 32 bit custom/XMS/VCPI system code
  1573. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1574. ;═════════════════════════════════════════════════════════════════════════════
  1575. cp_int31:                               ; INT 31h: AX=900h,901h,902h
  1576.         cmp al,1
  1577.         mov al,[esp+9]
  1578.         jb short cp_int31f0
  1579.         ja short cp_int31f1
  1580.         or byte ptr [esp+9],2
  1581.         jmp short cp_int31f1
  1582. cp_int31f0:
  1583.         and byte ptr [esp+9],0fdh
  1584. cp_int31f1:
  1585.         shr al,1
  1586.         and al,1
  1587.         iretd
  1588. ;═════════════════════════════════════════════════════════════════════════════
  1589. vp_int32:                               ; VCPI INT 32h: safe CX:DX=seg:off
  1590.         pushad
  1591.         mov ebp,offset callreal
  1592.         mov si,VICREAL1D
  1593.         mov bl,2
  1594.         jmp short cp_int34f0
  1595. ;═════════════════════════════════════════════════════════════════════════════
  1596. vp_int33:                               ; VCPI INT 33h: safe AL=int num
  1597.         pushad
  1598.         mov ebp,offset intreal
  1599. ;-----------------------------------------------------------------------------
  1600. vp_int33f0:
  1601.         mov si,VICREAL1D
  1602.         mov bl,2
  1603.         jmp short cp_int35f0
  1604. ;═════════════════════════════════════════════════════════════════════════════
  1605. cp_int32:                               ; INT 32h: safe CX:DX=seg:off
  1606.         pushad
  1607.         mov ebp,offset callreal
  1608.         mov si,CICREAL1D
  1609.         mov bl,1
  1610.         jmp short cp_int34f0
  1611. ;═════════════════════════════════════════════════════════════════════════════
  1612. cp_int33:                               ; INT 33h: safe AL=int num
  1613.         pushad
  1614.         mov ebp,offset intreal
  1615. ;-----------------------------------------------------------------------------
  1616. cp_int33f0:
  1617.         mov si,CICREAL1D
  1618.         mov bl,1
  1619.         jmp short cp_int35f0
  1620. ;═════════════════════════════════════════════════════════════════════════════
  1621. cp_int34:                               ; INT 34h: normal CX:DX=seg:off
  1622.         pushad
  1623.         mov ebp,offset callreal
  1624.         mov si,CICREAL0D
  1625.         xor bl,bl
  1626. ;-----------------------------------------------------------------------------
  1627. cp_int34f0:
  1628.         shl ecx,16
  1629.         mov cx,dx
  1630.         mov bh,1
  1631.         jmp short cp_int3_
  1632. ;═════════════════════════════════════════════════════════════════════════════
  1633. cp_int35:                               ; INT 35h: normal AL=int num
  1634.         pushad
  1635.         mov ebp,offset intreal
  1636. ;-----------------------------------------------------------------------------
  1637. cp_int35f1:
  1638.         mov si,CICREAL0D
  1639.         xor bl,bl
  1640. ;-----------------------------------------------------------------------------
  1641. cp_int35f0:
  1642.         movzx eax,al
  1643.         mov ecx,gs:[eax*4]
  1644.         xor bh,bh
  1645. ;-----------------------------------------------------------------------------
  1646. cp_int3_:                               ; int or call to real mode
  1647.         mov edi,[esp+40]
  1648.         shld eax,edi,23
  1649.         and al,bh
  1650.         add al,0fah
  1651.         mov edx,_code16a
  1652.         mov gs:icrealm0[edx],al
  1653.         mov gs:icrealm1[edx],ecx
  1654.         xchg gs:icrealm2[edx],si
  1655.         push si
  1656.         movzx esi,nextmodestack
  1657.         lea eax,[esi-STAKSAFE*16]
  1658.         mov nextmodestack,ax
  1659.         add eax,realstackbase
  1660.         mov edx,cp_tssesp0ptr
  1661.         push dword ptr [edx]
  1662.         mov [edx],eax
  1663.         sub eax,36
  1664.         push cp_validirqesp
  1665.         mov cp_validirqesp,eax
  1666.         push cp_savedstakoff
  1667.         mov cp_savedstakoff,esp
  1668.         cmp bl,1
  1669.         jb short cp_int3_n
  1670.         ja short vp_int3_s
  1671. ;-----------------------------------------------------------------------------
  1672. cp_int3_s:                              ; safe real mode int or call
  1673.         mov edx,_code16a
  1674.         mov gs:c_sicrealm0[edx],bp
  1675.         mov esp,esi
  1676.         db 0eah                 ; 16bit JMP FAR 20h:c_retreal0
  1677.         dw c_retreal0,0,20h     ;
  1678. ;-----------------------------------------------------------------------------
  1679. vp_int3_s:                              ; safe VCPI real mode int or call
  1680.         mov edi,ebp
  1681.         mov cx,v86r_ds
  1682.         mov ax,28h
  1683.         mov ds,ax
  1684.         db 0eah                 ; 16bit JMP FAR 20h:v_retreal0
  1685.         dw v_retreal0,0,20h     ;
  1686. ;-----------------------------------------------------------------------------
  1687. cp_int3_n:                              ; normal real mode int or call
  1688.         sub esp,8
  1689.         push dword ptr v86r_ds
  1690.         push dword ptr v86r_es
  1691.         db 68h                  ; 32bit PUSH codeend
  1692.         dd codeend              ;
  1693.         push esi
  1694.         or edi,20000h
  1695.         and di,0fdffh
  1696.         push edi
  1697.         db 68h                  ; 32bit PUSH code16
  1698.         dd code16               ;
  1699.         push ebp
  1700.         iretd
  1701. ;-----------------------------------------------------------------------------
  1702. cp_int3_d:                              ; done with real mode int or call
  1703.         mov ax,18h
  1704.         mov gs,ax
  1705.         mov ax,10h
  1706.         mov ds,ax
  1707.         mov es,ax
  1708.         mov fs,ax
  1709.         mov ss,ax
  1710.         mov esp,cp_savedstakoff
  1711.         pop cp_savedstakoff
  1712.         pop cp_validirqesp
  1713.         mov ebx,cp_tssesp0ptr
  1714.         pop dword ptr [ebx]
  1715.         mov ebx,_code16a
  1716.         pop gs:icrealm2[ebx]
  1717. ;-----------------------------------------------------------------------------
  1718. cp_int3_d3:                             ; done from real mode pmode call
  1719.         add nextmodestack,STAKSAFE*16
  1720.         mov bx,v86r_flags
  1721. ;-----------------------------------------------------------------------------
  1722. cp_int3_d2:                             ; done from DPMI also
  1723.         mov ax,[esp+40]
  1724.         and ax,not 8d5h
  1725.         and bx,8d5h
  1726.         or ax,bx
  1727.         mov [esp+40],ax
  1728.         popad
  1729.         iretd
  1730. ;═════════════════════════════════════════════════════════════════════════════
  1731. cp_excd:                                ; general protection violation
  1732.         cmp esp,cs:cp_validirqesp       ; source an IRQ or exception¿
  1733.         jne short cp_excdf0
  1734.         jmp cs:cp_int13vect
  1735. cp_excdf0:
  1736.         test byte ptr [esp+14],2        ; exception, from V86?
  1737.         jnz short cp_excdv86
  1738.         pushad                          ; nope, pmode exception
  1739.         mov al,0dh
  1740.         jmp cp_exc
  1741. ;-----------------------------------------------------------------------------
  1742. cp_excdv86:                             ; violation from V86 mode
  1743.         add esp,4
  1744.         pushad
  1745.         mov cx,18h
  1746.         mov ds,cx
  1747.         movzx ebx,word ptr [esp+36]
  1748.         shl ebx,4
  1749.         add ebx,[esp+32]
  1750.         inc word ptr [esp+32]
  1751.         mov al,[ebx]
  1752.         mov edx,3
  1753.         cmp al,0cch
  1754.         je short cp_v86int
  1755.         mov dl,4
  1756.         cmp al,0ceh
  1757.         je short cp_v86int
  1758.         inc word ptr [esp+32]
  1759.         mov dl,[ebx+1]
  1760.         cmp dl,32h
  1761.         je p_cpmode2
  1762.         cmp dl,0ffh
  1763.         je cp_int3_d
  1764. ;-----------------------------------------------------------------------------
  1765. cp_v86int:                              ; need to simulate a real mode int
  1766.         movzx ebx,word ptr [esp+48]
  1767.         shl ebx,4
  1768.         sub word ptr [esp+44],6
  1769.         add ebx,[esp+44]
  1770.         mov ax,[esp+40]
  1771.         mov [ebx+4],ax
  1772.         and ah,0fch
  1773.         mov [esp+41],ah
  1774.         mov ax,[esp+36]
  1775.         mov [ebx+2],ax
  1776.         mov ax,[esp+32]
  1777.         mov [ebx],ax
  1778.         mov eax,[edx*4]
  1779.         mov [esp+32],ax
  1780.         shr eax,16
  1781.         mov [esp+36],ax
  1782.         popad
  1783.         iretd
  1784. ;═════════════════════════════════════════════════════════════════════════════
  1785. ; all exceptions except 0dh. all are terminal, others are redirected.
  1786. cp_exc0:
  1787.         push eax
  1788.         mov ax,1000h
  1789.         jmp cp_irq
  1790. cp_exc1:
  1791.         push eax
  1792.         mov ax,1001h
  1793.         jmp cp_irq
  1794. cp_exc2:
  1795.         push eax
  1796.         mov ax,1002h
  1797.         jmp cp_irq
  1798. cp_exc3:
  1799.         pushad
  1800.         mov al,3
  1801.         jmp short cp_exc
  1802. cp_exc4:
  1803.         pushad
  1804.         mov al,4
  1805.         jmp short cp_exc
  1806. cp_exc5:
  1807.         push eax
  1808.         mov ax,1005h
  1809.         jmp cp_irq
  1810. cp_exc6:
  1811.         pushad
  1812.         mov al,6
  1813.         jmp short cp_exc
  1814. cp_exc7:
  1815.         push eax
  1816.         mov ax,1007h
  1817.         jmp cp_irq
  1818. cp_exc8:
  1819.         pushad
  1820.         mov al,8
  1821.         jmp short cp_exc
  1822. cp_exc9:
  1823.         pushad
  1824.         mov al,9
  1825.         jmp short cp_exc
  1826. cp_exca:
  1827.         pushad
  1828.         mov al,0ah
  1829.         jmp short cp_exc
  1830. cp_excb:
  1831.         pushad
  1832.         mov al,0bh
  1833.         jmp short cp_exc
  1834. cp_excc:
  1835.         pushad
  1836.         mov al,0ch
  1837.         jmp short cp_exc
  1838. cp_exce:
  1839.         pushad
  1840.         mov al,0eh
  1841.         jmp short cp_exc
  1842. cp_excf:
  1843.         pushad
  1844.         mov al,0ffh
  1845. ;-----------------------------------------------------------------------------
  1846. cp_exc:                                 ; main exception handler
  1847.         mov ax,10h
  1848.         mov ds,ax
  1849.         mov es,ax
  1850.         mov fs,ax
  1851.         mov gs,_selzero
  1852.         cld
  1853.         jmp _exit
  1854. ;═════════════════════════════════════════════════════════════════════════════
  1855. ; IRQ redirector between modes
  1856. cp_irq0:
  1857.         push eax
  1858.         mov ax,0008h
  1859.         jmp short cp_irq
  1860. cp_irq1:
  1861.         push eax
  1862.         mov ax,0109h
  1863.         jmp short cp_irq
  1864. cp_irq2:
  1865.         push eax
  1866.         mov ax,020ah
  1867.         jmp short cp_irq
  1868. cp_irq3:
  1869.         push eax
  1870.         mov ax,030bh
  1871.         jmp short cp_irq
  1872. cp_irq4:
  1873.         push eax
  1874.         mov ax,040ch
  1875.         jmp short cp_irq
  1876. cp_irq5:
  1877.         push eax
  1878.         mov ax,050dh
  1879.         jmp short cp_irq
  1880. cp_irq6:
  1881.         push eax
  1882.         mov ax,060eh
  1883.         jmp short cp_irq
  1884. cp_irq7:
  1885.         push eax
  1886.         mov ax,070fh
  1887.         jmp short cp_irq
  1888. cp_irq8:
  1889.         push eax
  1890.         mov ax,0870h
  1891.         jmp short cp_irq
  1892. cp_irq9:
  1893.         push eax
  1894.         mov ax,0971h
  1895.         jmp short cp_irq
  1896. cp_irqa:
  1897.         push eax
  1898.         mov ax,0a72h
  1899.         jmp short cp_irq
  1900. cp_irqb:
  1901.         push eax
  1902.         mov ax,0b73h
  1903.         jmp short cp_irq
  1904. cp_irqc:
  1905.         push eax
  1906.         mov ax,0c74h
  1907.         jmp short cp_irq
  1908. cp_irqd:
  1909.         push eax
  1910.         mov ax,0d75h
  1911.         jmp short cp_irq
  1912. cp_irqe:
  1913.         push eax
  1914.         mov ax,0e76h
  1915.         jmp short cp_irq
  1916. cp_irqf:
  1917.         push eax
  1918.         mov ax,0f77h
  1919. ;─────────────────────────────────────────────────────────────────────────────
  1920. cp_irq:                                 ; main IRQ handler thingy
  1921.         mov ss:cp_v86irqnum,al
  1922.         movzx eax,ah
  1923.         bt dword ptr ss:_irqmode,eax
  1924.         setc ss:cp_v86irqmode
  1925.         pop eax
  1926.         test byte ptr [esp+10],2
  1927.         jnz short cp_irqv86
  1928.         push ds es fs gs                ; real mode IRQ from pmode
  1929.         pushfd
  1930.         push cs
  1931.         push offset cp_irqpd
  1932.         pushad
  1933.         mov ax,10h
  1934.         mov ds,ax
  1935.         mov al,18h
  1936.         mov gs,ax
  1937.         mov al,cp_v86irqnum
  1938.         mov ebp,offset c_irqreal
  1939.         movzx ebx,cp_v86irqmode
  1940.         jmp cp_v86irqintr[ebx*4]
  1941. cp_irqpd:
  1942.         pop gs fs es ds
  1943.         iretd
  1944. ;─────────────────────────────────────────────────────────────────────────────
  1945. cp_irqv86:                              ; IRQ from V86, safe or norm redirect
  1946.         cmp cs:cp_v86irqmode,0
  1947.         jne short cp_irqv86s
  1948.         pushad                          ; normal IRQ redirection
  1949.         mov ax,18h
  1950.         mov ds,ax
  1951.         movzx edx,ss:cp_v86irqnum
  1952.         jmp cp_v86int
  1953. ;-----------------------------------------------------------------------------
  1954. cp_irqv86s:                             ; safe IRQ redirection
  1955.         pushfd
  1956.         push cs
  1957.         push offset cp_irqv86sd
  1958.         pushad
  1959.         mov ax,10h
  1960.         mov ds,ax
  1961.         mov al,18h
  1962.         mov gs,ax
  1963.         sub nextmodestack,STAKSAFE*16
  1964.         mov al,cp_v86irqnum
  1965.         mov ebp,offset c_irqreal
  1966.         jmp cp_v86irqintr[4]
  1967. ;-----------------------------------------------------------------------------
  1968. cp_irqv86sd:                            ; done with safe IRQ
  1969.         add nextmodestack,STAKSAFE*16
  1970.         iretd
  1971.  
  1972. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1973. ; Custom get IRQ handler offset
  1974. ; In:
  1975. ;   BL - IRQ num (0-0fh)
  1976. ; Out:
  1977. ;   EDX - offset of IRQ handler
  1978. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1979. cp_getirqvect:
  1980.         push ebx
  1981.         pushf
  1982.         cli
  1983.         movzx ebx,bl
  1984.         mov bl,intslottbl[ebx]
  1985.         cmp bl,13
  1986.         je short cp_getirqvectf0
  1987.         lea ebx,[ebx*8]
  1988.         add ebx,cp_idt32ptr
  1989.         mov dx,[ebx+6]
  1990.         shl edx,16
  1991.         mov dx,[ebx]
  1992. cp_getirqvectd:
  1993.         popf
  1994.         pop ebx
  1995.         ret
  1996. cp_getirqvectf0:
  1997.         mov edx,cp_int13vect
  1998.         jmp short cp_getirqvectd
  1999. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2000. ; Custom set IRQ handler offset
  2001. ; In:
  2002. ;   BL - IRQ num (0-0fh)
  2003. ;   EDX - offset of IRQ handler
  2004. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2005. cp_setirqvect:
  2006.         push ebx
  2007.         pushf
  2008.         cli
  2009.         movzx ebx,bl
  2010.         mov bl,intslottbl[ebx]
  2011.         cmp bl,13
  2012.         je short cp_setirqvectf0
  2013.         lea ebx,[ebx*8]
  2014.         add ebx,cp_idt32ptr
  2015.         mov [ebx],dx
  2016.         shr edx,16
  2017.         mov [ebx+6],dx
  2018. cp_setirqvectd:
  2019.         popf
  2020.         pop ebx
  2021.         ret
  2022. cp_setirqvectf0:
  2023.         mov cp_int13vect,edx
  2024.         jmp short cp_setirqvectd
  2025.  
  2026. code32  ends
  2027.  
  2028. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  2029. ; End of program (must be at end of program or you will suffer)
  2030. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  2031. codeend segment para stack use32 'stack'
  2032. db STAKLEN*16 dup(?)
  2033. codeend ends
  2034.         end     start16
  2035.  
  2036.